/* eslint-disable no-misleading-character-class */
import Vue from 'vue'

/**
 *  实现功能
 *  1、默认情况下只禁止空格输入
 *  2、限制只能输入整数
 *  3、限制只能输入整数和小数（价格类）
 */
const trigger = (el, type) => {
  const e = document.createEvent('HTMLEvents')
  e.initEvent(type, true, true)
  el.dispatchEvent(e)
}
const intFilter = function(el) {
  el.value = el.value.replace(/\D/g, '').length > 1 ? el.value.replace(/\D|\b(0+)/g, '') : el.value.replace(/\D/g, '')
  trigger(el, 'input')
}
const intAZFilter = function(el) {
  el.value = el.value.toUpperCase().replace(/_/g, '').replace(/[\W]/g, '').slice(0, 18)
  trigger(el, 'input')
}
const intAzFilter = function(el) {
  el.value = el.value.replace(/_/g, '').replace(/[\W]/g, '')
  trigger(el, 'input')
}
const switchfilter = function(el, arg, binding) {
  const changeList = {
    'int': intFilter, // 手机号类型
    'intAZ': intAZFilter, // 数字字母组合
    'intAz': intAzFilter, // 数字字母组合,允许小写
  }
  changeList[arg](el, binding)
}
const filterFunction = function(el, arg, binding) {
  var doing = false
  el.addEventListener('compositionstart', function(e) {
    doing = true
  }, false)
  el.addEventListener('keyup', function(e) {
    if (!doing) {
      switchfilter(el, arg, binding)
    }
  }, false)

  el.addEventListener('compositionend', function(e) {
    doing = false
    setTimeout(function() {
      switchfilter(el, arg, binding)
    }, 10)
  }, false)
}
var inputFilter = {
  bind(el, binding, vnode) {
    if (el.tagName.toLowerCase() !== 'input') {
      el = el.getElementsByTagName('input')[0] ? el.getElementsByTagName('input')[0] : el.getElementsByTagName('textarea')[0]
    }
    filterFunction(el, binding.arg, binding)
  }
}
Vue.directive('inputFilter', inputFilter)

// 适用于table-filter
var inputFilter2 = {
  bind(el, binding, vnode) {
    const filters = binding.value
    if (el.tagName.toLowerCase() !== 'input') {
      el = el.getElementsByTagName('input')[0] ? el.getElementsByTagName('input')[0] : el.getElementsByTagName('textarea')[0]
    }
    if (Array.isArray(filters)) {
      filters.forEach(filter => {
        filterFunction(el, filter)
      })
    } else if (filters) {
      filterFunction(el, filters)
    }
  }
}
Vue.directive('inputFilter2', inputFilter2)

// 适用于较长的弹框
Vue.directive('dialogDrag', {
  bind(el, binding, vnode, oldVnode) {
    const dialogWrapperEl = el
    const dialogHeaderEl = el.querySelector('.el-dialog__header')
    const dragDom = el.querySelector('.el-dialog')
    // dialogHeaderEl.style.cursor = 'move';
    dialogHeaderEl.style.cssText += ';cursor:move;'
    dragDom.style.cssText += ';top:0px;'
    // dialogWrapperEl.style.overflow = 'hidden' // 不锁定,超出后可以使用滚动条

    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = (function() {
      if (window.document.currentStyle) {
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {
      // 鼠标按下，计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const screenWidth = document.body.clientWidth // body当前宽度
      const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度，可某些环境下无法获取)

      const dragDomWidth = dragDom.offsetWidth // 对话框宽度
      const dragDomheight = dragDom.offsetHeight // 对话框高度

      let minDragDomLeft = -dragDom.offsetLeft
      let maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
      const reservedDistance = 80
      minDragDomLeft += -(dragDomWidth - reservedDistance)
      maxDragDomLeft += dragDomWidth - reservedDistance

      const minDragDomTop = -dragDom.offsetTop
      let maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
      maxDragDomTop += dragDomheight - reservedDistance

      // 获取到的值带px 正则匹配替换
      let styL = sty(dragDom, 'left')
      let styT = sty(dragDom, 'top')

      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
        styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
      } else {
        styL = +styL.replace(/\px/g, '')
        styT = +styT.replace(/\px/g, '')
      }

      // 去掉对拖拽的响应，参考：https://blog.csdn.net/z467469274/article/details/77332830?utm_source=blogxgwz2
      const ondragstartBackup = document.ondragstart
      const ondragendBackup = document.ondragend
      document.ondragstart = function(ev) {
        ev.preventDefault()
      }
      document.ondragend = function(ev) {
        ev.preventDefault()
      }

      document.onmousemove = function(e) {
        // 通过事件委托，计算移动的距离
        let left = e.clientX - disX
        let top = e.clientY - disY

        // 边界处理
        if (left < minDragDomLeft) {
          left = minDragDomLeft
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (top < minDragDomTop) {
          top = minDragDomTop
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }

        // 移动当前元素
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
      }

      document.onmouseup = function(e) {
        document.onmousemove = null
        document.onmouseup = null
        document.ondragstart = ondragstartBackup
        document.ondragend = ondragendBackup
      }
    }
  }
})

function adjustColumnWidth(table, padding = 32) {
  const colgroup = table.querySelector('colgroup')
  if (!colgroup) {
    return
  }
  table.classList.add('r-table')
  const colDefs = [...colgroup.querySelectorAll('col')]
  colDefs.forEach((col) => {
    const clsName = col.getAttribute('name')
    const cells = [
      ...table.querySelectorAll(`td.${clsName}`),
      ...table.querySelectorAll(`th.${clsName}`)
    ]
    if (cells[0].classList.contains?.('leave-alone')) {
      return
    }
    const widthList = cells.map((el) => {
      return el.querySelector('.cell')?.scrollWidth || 0
    })
    const max = Math.max(...widthList)
    setTimeout(() => {
      table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
        el.setAttribute('width', max + padding)
      })
    }, 100)
  })
}
// element-ui 列自适应宽度，有抖动，合理使用
Vue.directive('fit-columns', {
  componentUpdated(el, binding, vnode) {
    vnode.context.$once('rendered', function(value) {
      adjustColumnWidth(el, binding.value)
    })
  }
})
